package com.zhouyu.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Component
public class UserService {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private UserService userService;

	@Transactional()
	public ResultVo test()
	{
		jdbcTemplate.execute("insert user values(1, 'aaaaa')");
		// 注册事务
		TransactionSynchronizationManager.registerSynchronization(
				new TestTransactionSynchronization(TransactionSynchronizationManager.getCurrentTransactionName())
		);
		try {
			// a.(); 这样直接调用的话，a() 上的 @Transactional 注解失效，不会走事务模式
			userService.a();
		} catch (Exception e) {
			// 强制回滚
			//TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return new ResultVo(1, null, e.getMessage());
		}
		return null;
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void a() {
		TransactionSynchronizationManager.registerSynchronization(
				new TestTransactionSynchronization(TransactionSynchronizationManager.getCurrentTransactionName())
		);
		jdbcTemplate.execute("insert user values(2, 'bbbbb')");
		throw new NullPointerException();
	}
	public void test2(String a, String b, String c)
	{
		System.out.println("Invoke test2");
	}
}

class TestTransactionSynchronization implements TransactionSynchronization {

	private String txName;
	public TestTransactionSynchronization(String txName) {
		this.txName = txName;
	}
	@Override
	public int getOrder()
	{
		System.out.println("Order: "+TransactionSynchronization.super.getOrder());
		return TransactionSynchronization.super.getOrder();
	}

	@Override
	public void suspend()
	{
		System.out.printf("事务 %s 挂起%n", txName);
		TransactionSynchronization.super.suspend();
	}

	@Override
	public void resume()
	{
		System.out.printf("事务 %s 恢复%n", txName);
		TransactionSynchronization.super.resume();
	}

	@Override
	public void flush()
	{
		System.out.printf("事务 %s flush%n", txName);
		TransactionSynchronization.super.flush();
	}

	@Override
	public void beforeCommit(boolean readOnly)
	{
		System.out.printf("事务 %s 提交前%n", txName);
		TransactionSynchronization.super.beforeCommit(readOnly);
	}

	@Override
	public void beforeCompletion()
	{
		System.out.printf("事务 %s 完成前%n", txName);
		TransactionSynchronization.super.beforeCompletion();
	}

	@Override
	public void afterCommit()
	{
		System.out.printf("事务 %s 提交后%n", txName);
		TransactionSynchronization.super.afterCommit();
	}

	@Override
	public void afterCompletion(int status)
	{
		System.out.printf("事务 %s 完成后%n", txName);
		TransactionSynchronization.super.afterCompletion(status);
	}
}

class ResultVo {
	private int code;
	private Object data;
	private String string;

	public ResultVo(int code, Object data, String string)
	{
		this.code = code;
		this.data = data;
		this.string = string;
	}
}
